package com.landscope.issue.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.landscope.issue.entity.User;
import com.landscope.issue.exception.BizException;
import com.landscope.issue.exception.E_EXCEPTION_TYPE;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * token工具
 *
 * @author qzp
 * @version v1.0
 * @date 2021/6/28 14:42
 **/
@Slf4j
public class TokenUtil {

    private static final String SECRET = "7PbIFZYg";

    /**
     * 验证accessToken
     *
     * @param accessToken:
     * @return {@link * @return java.util.Map<java.lang.String,com.auth0.jwt.interfaces.Claim>}
     * @throws
     * @author 瞿子朋
     * @date 2021/8/2 13:47
     * @version v1.0
     **/
    public static Map<String, Claim> verifyAccessToken(String accessToken) {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(accessToken);
        } catch (Exception e) {
            throw BizException.noLoginException();
        }
        return jwt.getClaims();
    }

    /**
     * 验证发布服务器token有效性
     *
     * @param token:
     * @return {@link * @return java.util.Map<java.lang.String,com.auth0.jwt.interfaces.Claim>}
     * @throws
     * @author 瞿子朋
     * @date 2021/8/2 15:18
     * @version v1.0
     **/
    public static Integer verifyToken(String token) {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw BizException.noLoginException();
        }
        if (UserLogoutCacheUtils.get(token) != null)
            throw BizException.noLoginException();
        Map<String, Claim> map = jwt.getClaims();
        Claim c = map.get("id");
        if(c == null)
            return null;
        Integer userId = Integer.valueOf(c.asInt());
        return userId;
    }

    public static Integer verifyToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(Const.TOKEN_KEY);
        log.info("验证token:{}",token);
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw BizException.fail(E_EXCEPTION_TYPE.user_token_invalid);
        }
        if (UserLogoutCacheUtils.get(token) != null)
            throw BizException.noLoginException();
        Map<String, Claim> map = jwt.getClaims();
        Claim c = map.get("id");
        if(c == null)
            return null;
        Integer userId = Integer.valueOf(c.asInt());
        return userId;
    }

    public static Boolean verifyRole(String code) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(Const.TOKEN_KEY);
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw BizException.fail(E_EXCEPTION_TYPE.user_token_invalid);
        }
        if (UserLogoutCacheUtils.get(token) != null)
            throw BizException.noLoginException();
        Map<String, Claim> map = jwt.getClaims();
        Claim c = map.get("rolePermissionCode");
        String rolePermissionCode = c.asString();
        if (rolePermissionCode.contains(code)) {
            String[] strs = rolePermissionCode.split(";");
            for (String key : strs) {
                if (key.contains("=")) {
                    String[] strs2 = key.split("=");
                    if (code.equals(strs2[0])) {
                        if (strs2[1].equals("1"))
                            return true;
                    }
                }
            }
        }
        throw BizException.fail(E_EXCEPTION_TYPE.has_not_module_authority);
    }

    public static String getUserName() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(Const.TOKEN_KEY);
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw BizException.fail(E_EXCEPTION_TYPE.user_token_invalid);
        }
        if (UserLogoutCacheUtils.get(token) != null)
            throw BizException.noLoginException();
        Map<String, Claim> map = jwt.getClaims();
        Claim c = map.get("name");
        if (c == null)
            return "";
        String name = c.asString();
        return name;
    }

    /**
     * 退出登录，注销
     *
     * @param token:
     * @return {@link * @return void}
     * @throws
     * @author 瞿子朋
     * @date 2021/8/2 15:19
     * @version v1.0
     **/
    public static void logout(String token) {
        UserLogoutCacheUtils.put(token, token);
    }

    /**
     * 验证用户项目权限
     *
     * @param accessToken:
     * @return {@link * @return java.util.Map<java.lang.String,com.auth0.jwt.interfaces.Claim>}
     * @throws
     * @author 瞿子朋
     * @date 2021/8/2 14:11
     * @version v1.0
     **/
    public static User verifyAuthority(String accessToken, String productCode) {
        Map<String, Claim> map = TokenUtil.verifyAccessToken(accessToken);
        if (!map.containsKey("auth"))
            throw BizException.fail(E_EXCEPTION_TYPE.access_token_invalid);
        JSONObject data = JSONUtil.parseObj(map.get("auth").asString());
        if (!data.containsKey("user"))
            throw BizException.fail(E_EXCEPTION_TYPE.access_token_invalid);
        if (!data.containsKey("projectList"))
            throw BizException.fail(E_EXCEPTION_TYPE.has_not_authority);
        JSONObject jsonObject = data.getJSONObject("user");
        Integer userId = jsonObject.getInt("id");
        String userName = jsonObject.getStr("name");
        String account = jsonObject.getStr("account");
        String unitName = jsonObject.getStr("unitName");
        String rolePermissionCode = jsonObject.getStr("rolePermissionCode");
        String manageProjectCodes = jsonObject.getStr("manageProjectCodes");
        String str = data.getStr("projectList");
        String[] projects = str.split(",");
        User user = new User();
        user.setId(userId);
        user.setName(userName);
        user.setAccount(account);
        user.setUnitName(unitName);
        user.setManageProjectCodes(manageProjectCodes);
        user.setRolePermissionCode(rolePermissionCode);
        if (StrUtil.isEmpty(productCode))
            return user;
        for (String key : projects) {
            if (key.equals(productCode)) {
                return user;
            }
        }
        throw BizException.fail(E_EXCEPTION_TYPE.has_not_authority);
    }

    /**
     * 管理用户生成token
     *
     * @param userId:
     * @return {@link * @return java.lang.String}
     * @throws
     * @author 瞿子朋
     * @date 2021/6/28 14:48
     * @version v1.0
     **/
    public static String createToken(Integer userId, String userName, String rolePermissionCode) {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.HOUR, 8); // token过期时间8小时
//        nowTime.add(Calendar.SECOND, 20); // token过期时间8小时
        //过期时间
        Date expiresDate = nowTime.getTime();
        Map<String, Object> map = new HashMap<>();
        //声明类型和方法
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        String token = JWT.create()
                .withHeader(map)
                //自定义参数
                .withClaim("id", userId)
                .withClaim("name", userName)
                .withClaim("rolePermissionCode", rolePermissionCode)
                //过期时间
                .withExpiresAt(expiresDate)
                .withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(SECRET));
        return token;
    }

    public static void main(String[] strs) {
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoIjoie1wicHJvamVjdExpc3RcIjpcInluX2pwelwiLFwidXNlclwiOntcInVuaXROYW1lXCI6XCLmtYvor5XljZXkvY1cIixcIm1hbmFnZVByb2plY3RDb2Rlc1wiOlwieW5fanB6O3FoX2JsaFwiLFwibmFtZVwiOlwi556_5a2Q5pyLXCIsXCJyb2xlUGVybWlzc2lvbkNvZGVcIjpcInN0YWRfZW49MTtqY2FkX2VuPTE7dmJhZF9lbj0xO3hjYWRfZW49MTt2ZXJpZnlfZW49MTtcIixcImFjY291bnRcIjpcIjE1ODgyNzgxMDMyXCJ9fSIsImV4cCI6MTY2OTE5NjQ5MSwiaWF0IjoxNjY5MTY3NjkxfQ.2H4dkUhPjRFoz36IwlD01mWIO9M025TNxMmDx0oWnMM";
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw BizException.fail(E_EXCEPTION_TYPE.user_token_invalid);
        }
        if (UserLogoutCacheUtils.get(token) != null)
            throw BizException.noLoginException();
        Map<String, Claim> map = jwt.getClaims();
        for (String key :
                map.keySet()) {
            System.out.println(key+":"+map.get(key).asString());
        }
    }
}
